package com.prp.bo;

import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Transaction;

import com.prp.db.DAOFactory;
import com.prp.db.HibernateSessionFactory;
import com.prp.db.daoimpl.mysql.HibernateDAOFactory;
import com.prp.db.daoimpl.mysql.NeighbourRelationshipDAO;
import com.prp.db.idao.INeighbourRelationshipDAO;
import com.prp.db.idao.IUserInformationDAO;
import com.prp.db.idao.IUserRecommendationDAO;
import com.prp.db.po.NeighbourRelationship;
import com.prp.db.po.NeighbourRelationshipId;
import com.prp.db.po.UserInformation;
import com.prp.db.po.UserRecommendation;
import com.prp.gwt.client.vo.UserList;

public class Friend {

	@SuppressWarnings("unchecked")
	public static UserList getFriends(int userId) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		INeighbourRelationshipDAO relatioinDAO = factory
				.getNeighbourRelationshipDAO();
		IUserInformationDAO userDAO = factory.getUserInformationDAO();

		UserList userList = new UserList();
		userList.setOwner(User.parse(userDAO.findById(userId)));

		List<NeighbourRelationship> relation = relatioinDAO.findByProperties(
				new String[] { NeighbourRelationshipDAO.FROMID,
						NeighbourRelationshipDAO.BUILDUP }, new Object[] {
						userId, true });
		for (NeighbourRelationship neighbour : relation)
			userList.addUser(User.parse(userDAO.findById(neighbour.getId()
					.getToId())));

		relation = relatioinDAO.findByProperties(
				new String[] { NeighbourRelationshipDAO.TOID,
						NeighbourRelationshipDAO.BUILDUP }, new Object[] {
						userId, true });
		for (NeighbourRelationship neighbour : relation)
			userList.addUser(User.parse(userDAO.findById(neighbour.getId()
					.getFromId())));

		return userList;
	}

	public static UserList searchByUserName(String userName) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		IUserInformationDAO userDAO = factory.getUserInformationDAO();
		List<UserInformation> list = userDAO.findByNamePattern("%" + userName
				+ "%");
		UserList userList = new UserList();
		for (int i = 0; i < list.size() && i < 150; i++)
			userList.addUser(User.parse(list.get(i)));
		return userList;
	}

	public static boolean isNeighbour(int id1, int id2) {
		if (!User.hasUser(id1) || !User.hasUser(id2))
			return false;
		DAOFactory factory = DAOFactory.getDAOFactory();
		INeighbourRelationshipDAO relatioinDAO = factory
				.getNeighbourRelationshipDAO();
		return relatioinDAO.isNeighbour(id1, id2);
	}

	public static boolean buildup(int fromId, int toId) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		INeighbourRelationshipDAO relationDAO = factory
				.getNeighbourRelationshipDAO();
		NeighbourRelationship relation1 = relationDAO
				.findById(new NeighbourRelationshipId(fromId, toId));
		if (relation1 == null)
			return false;
		if (relation1.getBuildup())
			return true;
		NeighbourRelationship relation2 = relationDAO
				.findById(new NeighbourRelationshipId(toId, fromId));
		Transaction tx = null;
		try {
			tx = HibernateSessionFactory.getSession().beginTransaction();
			if (relation2 != null)
				relationDAO.delete(relation2);
			relation1.setBuildup(true);
			relationDAO.save(relation1);
			tx.commit();
			return true;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
			return false;
		}
	}

	public static void breakup(int id1, int id2) {
		DAOFactory factory = HibernateDAOFactory.getDAOFactory();
		INeighbourRelationshipDAO dao = factory.getNeighbourRelationshipDAO();
		NeighbourRelationship relation1 = null, relation2 = null;

		Transaction tx = null;
		try {
			tx = HibernateSessionFactory.getSession().beginTransaction();

			relation1 = dao.findById(new NeighbourRelationshipId(id1, id2));
			relation2 = dao.findById(new NeighbourRelationshipId(id2, id1));

			if (relation1 != null && relation1.getBuildup()) {// is neighbour
				dao.delete(relation1);
				if (relation2 != null)
					dao.delete(relation2);
				tx.commit();
				return;
			}
			if (relation2 != null && relation2.getBuildup()) {
				dao.delete(relation2);
				if (relation1 != null)
					dao.delete(relation1);
				tx.commit();
				return;
			}
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}
	}

	public static boolean invite(int fromId, int toId) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		INeighbourRelationshipDAO relatioinDAO = factory
				.getNeighbourRelationshipDAO();
		NeighbourRelationship relation = relatioinDAO
				.findById(new NeighbourRelationshipId(fromId, toId));
		// record exists
		if (relation != null)
			return !relation.getBuildup();

		relation = new NeighbourRelationship(new NeighbourRelationshipId(
				fromId, toId), false);
		Transaction tx = null;
		try {
			tx = HibernateSessionFactory.getSession().beginTransaction();
			relatioinDAO.save(relation);
			tx.commit();
			return true;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
			return false;
		}
	}

	@SuppressWarnings("unchecked")
	public static UserList findInvite(int toId) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		INeighbourRelationshipDAO relatioinDAO = factory
				.getNeighbourRelationshipDAO();
		IUserInformationDAO userDAO = factory.getUserInformationDAO();
		List<NeighbourRelationship> nrList = relatioinDAO.findByProperties(
				new String[] { NeighbourRelationshipDAO.TOID,
						NeighbourRelationshipDAO.BUILDUP }, new Object[] {
						toId, false });
		UserList userList = new UserList();
		userList.setOwner(User.parse(User.getUser(toId)));
		for (NeighbourRelationship nr : nrList) {
			UserInformation userInfo = userDAO.findById(nr.getId().getFromId());
			userList.addUser(User.parse(userInfo));
		}
		return userList;
	}

	public static void cancelInvite(int fromId, int toId) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		INeighbourRelationshipDAO relatioinDAO = factory
				.getNeighbourRelationshipDAO();
		NeighbourRelationship relation = relatioinDAO
				.findById(new NeighbourRelationshipId(fromId, toId));
		// haven't invited or already neighbours
		if (relation == null || relation.getBuildup())
			return;

		Transaction tx = null;
		try {
			tx = HibernateSessionFactory.getSession().beginTransaction();
			relatioinDAO.delete(relation);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.commit();
			e.printStackTrace();
		}
	}

	public static void recommend(int userId, Set<Integer> fromIds,
			Set<Integer> toIds) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		IUserRecommendationDAO uDao = factory.getUserRecommendationDAO();
		if (!User.hasUser(userId))
			return;
		for (int fromId : fromIds)
			for (int toId : toIds) {
				if (User.hasUser(fromId) && User.hasUser(toId))
					if (!isNeighbour(fromId, toId))
						if (!uDao.findByExample(userId, fromId, toId)) {
							Transaction tx = null;
							try {
								tx = HibernateSessionFactory.getSession()
										.beginTransaction();
								UserRecommendation ur = new UserRecommendation();
								ur.setUserId(userId);
								ur.setFromId(fromId);
								ur.setToId(toId);
								uDao.save(ur);
								tx.commit();
							} catch (HibernateException e) {
								if (tx != null)
									tx.commit();
								e.printStackTrace();
							}
						}
			}
	}

	public static void deleteRecommend(int id) {
		DAOFactory factory = DAOFactory.getDAOFactory();
		IUserRecommendationDAO uDao = factory.getUserRecommendationDAO();
		Transaction tx = null;
		try {
			tx = HibernateSessionFactory.getSession().beginTransaction();
			UserRecommendation ur = uDao.findById(id);
			uDao.delete(ur);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.commit();
			e.printStackTrace();
		}
	}

	public static UserList getRecommendList(int toId){
		DAOFactory factory = DAOFactory.getDAOFactory();
		IUserRecommendationDAO uDao = factory.getUserRecommendationDAO();
		UserList userList = new UserList();
		List<UserRecommendation> list = uDao.findByToId(toId);
		for(UserRecommendation ur: list){
			com.prp.gwt.client.vo.User fromUser = User.parse(User.getUser(ur.getFromId()));
			fromUser.setRecommender(User.parse(User.getUser(ur.getUserId())));
			userList.addUser(fromUser);
			fromUser.setRecommendId(ur.getId());
		}
		return userList;
	}
//	
//	public static void main(String [] args){
//		System.out.println(getRecommendList(300).size());
//	}
	
}
